import React, { Component } from 'react'
// 提到生命周期钩子函数，意味着只在类组件
// 新版本：react 16.3版本以后
//    初始化  ---- 挂载时
//      constructor                   *****
//      static getDerivedStateFromProps()  *
//      render                        **********
//      componentDidMount             ********    vue  mounted
//    运行时阶段 ---- 更新时
//      static getDerivedStateFromProps() *
//      shouldComponentUpdate         ******    提升性能的关键
//      render                        **********
//      getSnapshotBeforeUpdate()     *
//      componentDidUpdate            ********  一定条件下可以修改组件的状态
//    销毁阶段
//      componentWillUnmount          ****
//    错误异常
//      static getDerivedStateFromError()
//      componentDidCatch             错误异常钩子函数，可用可不用

export default class App extends Component {
  // 如果不初始化 state 或不进行方法绑定，则不需要为 React 组件实现构造函数。
  constructor (props) {
    super(props)
    // this.fn = this.fn.bind(this)
    this.state = {
      a: 1
    }
  }
  // getDerivedStateFromProps 会在调用 render 方法之前调用，
  // 并且在初始挂载及后续更新时都会被调用。
  // 它应返回一个对象来更新 state，如果返回 null 则不更新任何内容。
  // static getDerivedStateFromProps (props, state) {
  //   // 此方法适用于罕见的用例，即 state 的值在任何时候都取决于 props。
  //   return {
  //     a: 100
  //   }
  // }
  // render 既存在于 挂载时阶段，也存在于更新时阶段
  render() {
    return (
      <div>
        { this.state.a }
      </div>
    )
  }
  // 会在组件挂载后（插入 DOM 树中）立即调用。
  // 依赖于 DOM 节点的初始化应该放在这里。
  // 如需通过网络请求获取数据，此处是实例化请求的好地方。
  componentDidMount () {
    // 实例化操作，DOM操作，数据请求。。。
    this.setState({
      a: 1000
    })
    // this.forceUpdate(); // 强制更新 ---- 一般不建议使用
  }
  // 提升react性能的关键，要不不写，要写必须得写返回值，默认返回值为true
  // 如果一定能使用 this.forceUpdate(); 强制更新，此钩子函数将不再执行
  shouldComponentUpdate (nextProps, nextState) {
    // return false
    return true
  }
  // 在最近一次渲染输出（提交到 DOM 节点）之前调用。
  // 它使得组件能在发生更改之前从 DOM 中捕获一些信息（例如，滚动位置）。
  // 此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
  getSnapshotBeforeUpdate (prevProps, prevState) {
    return '11223344'
  }

  // componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。
  componentDidUpdate (prevProps, prevState, snapshot) {
    // 最后一次修改状态的地方 ---- 必须得是在一定的条件内部
    // DOM操作
    // 实例化的操作
    console.log(snapshot)
  }

  componentWillUnmount () {
    // 卸载
  }
}
